package pers.jsan.litheopen.security.filter.client;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import pers.jsan.litheopen.security.cache.CacheClientManager;
import pers.jsan.litheopen.security.exception.LitheAuthenticationException;
import pers.jsan.litheopen.security.filter.AuthenticationFilterChain;
import pers.jsan.litheopen.security.filter.LitheAuthenticationFilter;
import pers.jsan.litheopen.security.filter.RequestWrapper;
import pers.jsan.litheopen.security.oauth.model.ClientAccess;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class ClientAccessRequestTimesFilter implements LitheAuthenticationFilter {

    private final static long MAX_TIME = 10L;   //一定时间内，大于等于一定次数拉黑名单
    private final static long MAX_EXPIRES = 30; //一定时间内最多请求次数
    private final static long BLACK_MAX_EXPIRES = 7000; //黑名单时间

    @Autowired
    private CacheClientManager redisClientManager;

    @Override
    public void doFilter(HttpServletRequest servletRequest, HttpServletResponse servletResponse, AuthenticationFilterChain filterChain) throws IOException, ServletException, LitheAuthenticationException {
        RequestWrapper requestWrapper = new RequestWrapper(servletRequest);
        String str = requestWrapper.getBodyString();
        JSONObject jsonObject = JSONObject.parseObject(str);
        ClientAccess clientAccess = jsonObject.toJavaObject(ClientAccess.class);
        Long times = redisClientManager.requestAccessTokenTimes(clientAccess);
        if(times >= MAX_TIME) {
            redisClientManager.cacheRequestAccessTokenTimes(clientAccess, MAX_TIME, BLACK_MAX_EXPIRES);
            throw new LitheAuthenticationException("请求过于频繁，"+BLACK_MAX_EXPIRES+"秒内禁止请求");
        }
        times++;
        //刷新请求次数
        redisClientManager.cacheRequestAccessTokenTimes(clientAccess, times, MAX_EXPIRES);
        filterChain.doFilter(servletRequest, servletResponse);
    }
}
